#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import json
import os
import traceback
import web
import time
import datetime

from sqlalchemy.orm.exc import NoResultFound

from Umpweb.base import render_jinja
from Umpweb.common import utils
from Umpweb.common.utils import xx, yy, get_current_user, conv_float, byte2GB 
from Umpweb.common.utils import login_required 
from Umpweb.db import api as db_api
from Umpweb.base import session, _


urls = (
        '/add',                 'HostAdd',
        '/config',              'HostConfig',
        '/import',              'HostImport',
        '/delete',              'HostDelete',
        '/start',               'HostStart',
        '/stop',                'HostStop',
        '/list',                'HostList',
        '/grid',                'GridHost',
        '/jquery_unitflot',     'JqueryUnitflot',
)

      
app = web.application(urls, locals())
render = render_jinja('static/templates/host', encoding='utf-8',)

class HostConfig:
    @login_required
    def GET(self):
        return render.host_config_page()


class HostAdd:
    @login_required
    def GET(self):
        clusters = db_api.cluster_get_all()
        return render.host_add_page(clusters=clusters)


    @login_required
    def POST(self):
        x = web.input()
        web.header("Content-Type", "application/json")

        ip = x['ip'].strip()
        ips = [_.strip() for _ in ip.split(',') if _]

        pwds = x['password'].strip()
        pwds = [_.strip() for _ in pwds.split(' ') if _]

        # if 'network' in x, the cluster does not exist yet, we should config first.
        if 'network' in x:
            networks = x['network'] + '/' + x['netmask']
            iscsi_vip = x['vip'] + '/' + x['netmask']
            nohosts = None
            if x['nohosts'] == 'true':
                nohosts = 'on'

            body = {
                "ClusterInitLichConfig": {
                    'params': {
                        'networks': networks,
                        'iscsi_vip': iscsi_vip,
                        'nohosts': nohosts,
                        'host': ips[0],
                    }
                }
            }
            res = utils.web_return(body)
            if not json.loads(res).get('reply', {}).get('is_success'):
                return res

        values = {
                'name':x['name'].strip(),
                'is_force':x['is_force'],
                'ips':ips,
                'user':'root',
                'passwd':pwds,
                # 'cluster_id':x['cluster_id']
               }
        body = {'HostAdd': {'params':values}}
        return utils.web_return(body)

class Base_host():
    def lichd_and_join(self,host):
        if host.is_join:
            host.is_join_show = '<span style="width:50px;display:inline-block;">在线:</span><img id="host_isjoin_%s"class="lichd" src="/static/img/green_status.png"/></br>'%host.id
            host.join_show = '是'
        else:
            host.is_join_show = '<span style="width:50px;display:inline-block;">在线:</span><img id="host_isjoin_%s" class="lichd" src="/static/img/red_status.png"/></br>'%host.id
            host.join_show = '否'
        if host.status == 'unknown':
            host.is_join_show = '<span style="width:50px;display:inline-block;">在线:</span><img id="host_isjoin_%s" class="lichd" src="/static/img/red_status.png"/></br>'%host.id
            host.join_show = '否'
        return host

    def host_info(self,host):
        disks = db_api.disk_get_isjoin_device(host.id, False)
        host.disk_number = len(disks)
        
        if host.usage_mem != None:
            host.usage_mem_ =  "%.0f%%" %(float(host.usage_mem)*100)
            #host.usage_mem_ = "%.2f%%" % (float(host.usage_mem) * 100)
        else:
            host.memory_total = 0
            host.usage_mem_ =  "%.0f%%" %(0)

        if host.cpu_util != None:
            host.usage_cpu_ =  "%.0f%%" %(float(host.cpu_util)*100)
        else:
            host.usage_cpu_ =  "%.0f%%" %(0)
        if host.usage_disk:
            host.usage_disk_ =  "%.0f" % conv_float(host.usage_disk * 100)
        else:
            host.usage_disk_ =  "%.0f" %(0)
            host.disk_total_kb = 0
        if host.usage_swap != None:
            host.usage_swap_ =  xx(host.usage_swap)
            host.usage_swap_ =  "%.0f%%" %(float(host.usage_swap_))
        else:
            host.usage_swap_ =  "%.0f%%" %(0)
        host.mem_total_ = yy(int(host.mem_total), 1024*1024)
        host.mem_total_ = int(host.mem_total_)
        if host.disk_total:
            disk_total_ = conv_float(byte2GB(host.disk_total))
            host.disk_total_ = "%.0fT" % conv_float(disk_total_ / 1024) if disk_total_ > 1024 else "%.0fG" % conv_float(disk_total_)
        else:
            # host.disk_total_ = '0.00G'
            host.disk_total_ = '0G'
        host.disk_total_kb = host.disk_total_

        if host.status == None:
            host.status = 'unknown'
        if host.status == 'unknown':
            # host.usage_cpu_ =  "0.00"
            # host.usage_mem_ =  "0.00"
            host.usage_cpu_ = "0"
            host.usage_mem_ = "0"
        host.swap_total = 0
        if host.status == 'running':
            host.link_show = '<span style="width:50px;display:inline-block;">连接:</span><img class="lichd" src="/static/img/green_status.png"/></br>'
        else:
            host.link_show = '<span style="width:50px;display:inline-block;">连接:</span><img class="lichd" src="/static/img/red_status.png"/></br>'
            host.is_join = False
        
        if hasattr(host,'mem'):
            swap = host.mem['swap_total']
            host.swap_total = yy(int(swap), 1024*1024)
        host.ip_show = host.ip
        
        host.lichd_show = ''
        lichd_show = '<span style="width:50px;display:inline-block;">进程:</span><img class="lichd" src="/static/img/red_status.png"/></br>'
        host.lichd_running_num = 0
        if host.lichd_status == 'running':
            lichd_show = '<span style="width:50px;display:inline-block;">进程:</span><img class="lichd" src="/static/img/green_status.png"/></br>'
            host.lichd_running_num = 1

        host.lichd_show = lichd_show 
        host.lichd_num = 1
        return host

class HostList:
    @login_required
    def GET(self):
        clusters = db_api.cluster_get_all()
        hosts = db_api.host_get_all()
        return render.host_list_page(clusters=clusters,hosts=hosts)

class HostImport:
    @login_required
    def GET(self):
        x = web.input()
        option = 'import'
        return render.host_import_page(option=option)

class GridHost(Base_host):
    @login_required
    def GET(self):
        web_input = web.input()
        filters = {}
        if 'host_id' in web_input.keys():
            host_id = web_input['host_id']
            if host_id:
                filters['host_id'] = host_id

        table = db_api.host_table
        if hasattr(web_input, 'cluster_id'):
            filters['cluster_id'] = web_input.get('cluster_id', '')

        page, total, records, rows = utils.grid_rows_query(table,web_input,filters)
        for host in rows:
            host = self.host_info(host)
            
            if host.protection_domain_id:
                protection_domain = db_api.protection_domain_get(host.protection_domain_id)
                host.protection_domain = protection_domain.name
            

        cells = ['id', 'name', 'ip_show', 'status','lichd_status', 'protection_domain',
                'disk_number', 'join_show','cpu_cores_num', 'usage_cpu_','mem_total_',
                'usage_mem_','disk_total_', 
                'usage_disk_',  'swap_total', 'lichd_status', 'mds_total', 'mds_running', 'cds_total', 'cds_running']
        rows_json = utils.grid_json(page, total, records, rows, 'id', cells)
        web.header("Content-Type", "application/json")
        return rows_json

class HostDelete:
    def POST(self):
        x = web.input()
        web.header("Content-Type", "application/json")
        host_id = x.get('host_id')
        values = {'host_id':host_id}
        body = {'HostDelete':{'params':values}}
        return utils.web_return(body)

class HostStart:
    def POST(self):
        x = web.input()
        host_id = x.get('host_id')
        web.header("Content-Type", "application/json")
        values = {'host_id':host_id}
        body = {'HostStart':{'params':values}}
        return utils.web_return(body)

class HostStop:
    def POST(self):
        x = web.input()
        web.header("Content-Type", "application/json")
        host_id = x.get('host_id')
        values = {'host_id':host_id}
        body = {'HostStop':{'params':values}}
        return utils.web_return(body)

class Host_info(Base_host):
    def GET(self, id):
        web_input = web.input()
        cluster = db_api.cluster_get(id)
        host_id = web_input['host_id']
        if host_id == '':
            return ''
        rownum = 1
        clusterhosts = db_api.host_get_with_cluster(cluster.id)
        for host in clusterhosts:
            hostdisks = db_api.disk_get_with_host(host_id)
            rownum += len(hostdisks)
        cluster.rownum = rownum
        host = db_api.host_get(host_id)
        hostdisks = db_api.disk_get_with_host(host_id)
        devices = hostdisks
        errs = [device['error'] for device in devices if 'error' in dir(device)]
        err = ''
        if len(errs) >0:
            err = str(errs[0])
            err = err.split('\n')
            err = (',').join(err)
        host = self.host_info(host)
        regep = re.compile(r'(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}')
        http_host = web.ctx.env.get('HTTP_HOST','')
        http_host = ",".join(set(regep.findall(http_host)))
        return render.node_info_page(cluster=cluster,host=host,err=err,http_host=http_host)

class JqueryUnitflot(Base_host):
    def GET(self):
        web.header("Content-Type", "application/json")
        x = web.input()
        cluster_id = x.get('cluster_id')
        host_id = x.get('host_id')
        try:
            cluster = db_api.cluster_get(cluster_id)
        except Exception,e:
            return json.dumps([])
        data = []
        hostids = x.get('hostids','').split(',')

        gridload = 'false'
        hosts_ = []
        for hostid in hostids:
            if not hostid:
                continue
            try:
                node = db_api.host_get(hostid) 
                hosts_.append(node)
            except Exception,e:
                gridload = 'true'
                pass

        hosts = []
        if not host_id is None and host_id != '' :
            hosts_ = [db_api.host_get(host_id)]
            raise
        data1,data2,data3,data4 = [],[],[],[]

        hosts_ = sorted(hosts_, key=lambda x :x.id)
      #  hosts_.reverse()
        stats = []
        for host in hosts_:
            if host.cpu_util != None:
                host.usage_cpu_ = "%.0f" %(float(json.loads(host.cpu_util))*100)
            else:
                host.usage_cpu_ =  '0.00'
            host.usage_mem_ = host.usage_mem
            if host.usage_mem != None:
                host.usage_mem_ =  "%.0f"%(float(host.usage_mem_)*100)
            else:
                host.usage_mem_ =  "0.00"
            if host.usage_swap != None:
                host.usage_swap_ =  "%s"%xx(host.usage_swap)
            else:
                host.usage_swap_ =  "0"
                #host.usage_swap_ = "0.00"

            iops = host.iops_str
            host.iops_read,host.iops_write = 0,0
            host.iops_spit,host.iops_swallow = 0,0
            if iops is not None and host.is_join and host.status == 'running':
                host.iops_read,host.iops_write =\
                                iops['_read'],iops['_write']
                host.iops_spit,host.iops_swallow = \
                                iops['_out'],iops['_in']
            if host.status == 'unknown':
                # host.usage_cpu_ =  "0.00"
                # host.usage_mem_ =  "0.00"
                host.usage_cpu_ = "0"
                host.usage_mem_ = "0"

            data.insert(0,host.usage_mem_)
            data.insert(0,host.usage_cpu_)
            data.insert(0,int(host.iops_spit))
            data.insert(0,int(host.iops_swallow))
            data.insert(0,int(host.iops_write))
            data.insert(0,int(host.iops_read))

            data1.append(int(host.iops_spit))
            data2.append(int(host.iops_swallow))
            data3.append(int(host.iops_write))
            data4.append(int(host.iops_read))

            host = self.host_info(host)
            stats.insert(0,host.service_status)

        if not data4 == []:
            data.append(int(max(data4)))
            data.append(int(max(data3)))
            data.append(int(max(data2)))
            data.append(int(max(data1)))
        data.append(','.join(stats))
        data.append(gridload)

        return json.dumps(data)

